package edu.vt.cbil.dataset;

import edu.vt.cbil.util.BioToolbox;
import edu.vt.cbil.util.ChartXYLine;
import edu.vt.cbil.util.GeneRange;
import edu.vt.cbil.util.Histogram;
import org.jfree.data.xy.XYSeries;
import org.jfree.graphics2d.svg.SVGGraphics2D;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author Justin
 * @version 1.0
 * @created 09-11-2014 11:52:23
 */
public class BioCollection implements Serializable {

    private static final long serialVersionUID = -6929767371951482440L;
    public List<Short> ChrIdInterested;
    public ResultContainer results;
    private transient Logger m_log;
    private List<GeneRange> roiArray;
    private Map<String, BioSample> samples;
    private transient AnnotationDataSet p_AnnotationData;

    public BioCollection(AnnotationDataSet pa) {
        resetLogger();

        setAnnotationData(pa);

        roiArray = null;

        samples = new HashMap<String, BioSample>();

        ChrIdInterested = new ArrayList<Short>();

        results = new ResultContainer();

    }

    public void setAnnotationData(AnnotationDataSet pa) {
        p_AnnotationData = pa;
    }

    public boolean addNewSample(String sampleId) {
        if (!samples.containsKey(sampleId)) {
            BioSample bs = new BioSample(sampleId);
            samples.put(sampleId, bs);
        } else {
            System.out.println("Duplicate sample Id!");
            return false;
        }
        return true;
    }

    public BioSample getSample(String sampleId) {
        return samples.get(sampleId);
    }

    public void setSamples(String sampleId, BioSample sample) {
        this.samples.put(sampleId, sample);
    }

    public void releaseSample(String sampleId) {
        samples.get(sampleId).clear();
    }

    public Chromosome getChromosome(String sampleId, int ChrId) {
        return samples.get(sampleId).getChromosome(ChrId);
    }

    public void resetLogger() {
        m_log = Logger.getLogger("edu.vt.cbil.bacom2");
    }

    public void setRoiArray(ArrayList<GeneRange> roiArray) {
        this.roiArray = roiArray;

        for (GeneRange g : roiArray) {
            ChrIdInterested.add(g.Chr_id);
        }
        // Collections.sort(ChrIdInterested);
    }

    public List<Short> getChrIdArray() {
        return ChrIdInterested;
    }

    public boolean isInterestedChromonsome(Short chrid) {
        for (Short s : ChrIdInterested) {
            if (s.equals(chrid))
                return true;
        }
        return false;
    }

    public void saveToDB(String sampleId, String filename, int selectTag) {
        BioSample sample = this.getSample(sampleId);

        try {
            Class.forName("org.sqlite.JDBC");
            String ConnectionString = String.format("jdbc:sqlite:%s", filename);
            Connection c = DriverManager.getConnection(ConnectionString);
            c.setAutoCommit(false);

            Statement stmt = c.createStatement();

            StringBuilder insertSql = new StringBuilder();


            insertSql.append("DELETE from cn;");
            int count = 0;
            part1:
            for (Short index : ChrIdInterested) {
                for (ProbeSet p : sample.getAllProbeSets(index).values()) {
                    if (p.data.Is_Valid) {
                        insertSql.append(String.format("INSERT INTO cn (Loci,Chr_id,Start,copynumber) " +
                                "VALUES (%d, %d, %d, %.10f);"
                                , p.Loci, p.Chr_id, p.Start, p.data.CopyNumberHalf));
                    }
                    count++;
                    if (count > 3000) {
//                        stmt.executeUpdate(insertSql.toString());
//                        insertSql.delete(0,insertSql.length());
                        count = 0;
                        System.out.println(p.Chr_id + ":" + p.Start);
                    }
                }
            }
            stmt.executeUpdate(insertSql.toString());

            stmt.close();
            c.commit();
            c.close();

        } catch (Exception e) {
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
            System.exit(0);
        }
    }

    public void printSegmentsString(String sampleId, int index) {
        BioSample sample = this.getSample(sampleId);
        m_log.info(String.format("%n#### #### #### chr %02d Second Step: Segments Count = %d",
                index, sample.getAllSegments(index).size()));
        int i = 0;
        for (Segment s : sample.getAllSegments(index)) {
            m_log.info(s.getCharacterString());
            i++;
            if (i > 20) {
                m_log.info("Omit......");
                break;
            }

        }
    }


    public void averagePloidy(String sampleId) {
        BioSample sample = this.getSample(sampleId);
        double sum = 0;
        int count = 0;
        for (Short index : ChrIdInterested) {
//            for (ProbeSet p : sample.getAllProbeSets(index).values()) {
//                if (p.data.Is_Valid) {
//                    sum += p.data.CopyNumberHalf;
//                    count++;
//                    h.addDataPoint(p.data.CopyNumberHalf);
//                }
//            }
            for (Segment seg : sample.getAllSegments(index)) {

                count += seg.Loci.size();

                sum += seg.purityCorrCopyNumber * seg.Loci.size();
            }
        }
        double mean = sum / count;
        results.setPloidy(sampleId, mean);

        m_log.info(String.format("%s : Average Ploidy = %.5f \t Probe count = %d %n%n ",
                sampleId, mean, count));
    }

    public void drawSegmentHistogram(String sampleId) {
        Histogram h = new Histogram(256, 0, 10);
        BioSample sample = this.getSample(sampleId);
        for (Short index : ChrIdInterested) {
            for (Segment seg : sample.getAllSegments(index)) {
                h.addDataPoint(seg.purityCorrCopyNumber, seg.Loci.size());
//                h.addDataPoint(seg.robustMeanHalfCopyNumber*2, seg.Loci.size());
            }
        }

        String result = String.format("%s:Ploidy = %.4f \t Purity = %.4f", sampleId, results.getPloidy(sampleId),
                results.getPurity(sampleId));

        XYSeries xyseries = new XYSeries("CopyNumber");

        for (int i = 1; i < h.getBin(); i++) {
            xyseries.add(h.getThresh(i), h.getFreq(i));
        }
        ChartXYLine cxy = new ChartXYLine();
        cxy.addLine(xyseries);

        h.clear();
        xyseries = new XYSeries("balanced");

        for (Short i : this.getChrIdArray()) {
            Map<Long, ProbeSet> chromosome = sample.getAllProbeSets(i);
            for (Segment s : sample.getAllSegments(i)) {
                double avg = s.purityCorrCopyNumber;
//                double avg =  s.robustMeanHalfCopyNumber*2;
                for (Long id : s.Loci.keySet()) {
                    ProbeSet ps = chromosome.get(id);
                    if (ps.Is_SNPProbe && ps.data.isNotLOH
                            && (ps.data.Normal.isGenotypeAB)
                            ) {
                        h.addDataPoint(avg);
                    }
                }
            }
        }
        for (int i = 1; i < h.getBin(); i++) {
            xyseries.add(h.getThresh(i), h.getFreq(i));
        }
        cxy.addLine(xyseries);
        cxy.createChart(result, "Copy Number", "Count");

        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String filename = String.format("..%1$sData%1$s%2$s_%3$s_%4$s.png",
                File.separator, "HistogramSegment", sampleId, df.format(date));

        cxy.saveAsFile(filename, 600, 400);
//        cxy.saveAsFile(filename, 320, 200);
    }

    public void printBaselineArray(String sampleId) {
        BioSample sample = this.getSample(sampleId);
        for (Short i : ChrIdInterested) {
            m_log.info(String.format("chr_id = %2d;\t Seg count = %5d \t baseline = %.5f", i,
                    sample.getAllSegments(i).size(),
                    sample.getChromosome(i).baseline));
        }
        m_log.info(String.format("Global base;\t \t \t \t \t \t baseline = %.5f",
                sample.getChromosome(0).baseline));
    }

    public void calculateResults(String sampleId) {
        BioSample sample = this.getSample(sampleId);


        for (Short i : getChrIdArray()) {
            Map<Long, Integer[]> chrResult = results.probeSetGraph.get(i);

            for (ProbeSet ps : sample.getAllProbeSets(i).values()) {
                Integer[] newArray = new Integer[]{0, 0, 0, 0};//Deletion,Normal,amplification, invalid

                if ((ps.data.Is_Valid) && (ps.data.parent_segment != null)) {

                    SegmentFeature sf = ps.data.parent_segment.fVector;

                    if (sf.isDeletion) {
                        if (sf.isHomoDeletion) {
                            newArray[0] = 1;
                        } else {
                            newArray[0] = 1;
                        }

                    } else if (sf.isNeutral) {
                        newArray[1] = 1;
                    } else {
                        newArray[2] = 1;
                    }
                } else {
                    newArray[3] = 1;
                }

                if (chrResult.containsKey(ps.Loci)) {
                    Integer[] oldArray = chrResult.get(ps.Loci);
                    for (int j = 0; j < oldArray.length; j++) {
                        newArray[j] += oldArray[j];
                    }
                }
                chrResult.put(ps.Loci, newArray);
            }
        }
    }

    public void drawResult() {

        Map<Long, String> CytobandCache = new HashMap<Long, String>(180 * 10000);
        for (AnnotationProbeSet aps : p_AnnotationData.getProbeSets().values()) {
            CytobandCache.put(aps.Pos, aps.Cytoband);
        }

        int x, y,
                sx, step;
        int scaleX = 40;
        int scaleY = 20;
        int scaleY2 = 8;
        int height = (int) (1.5 * scaleY);
        sx = 2;

        int width = 400000 / scaleX;

        SVGGraphics2D svg = new SVGGraphics2D(width, 5 * scaleY * 26);

        int[] colorValue = new int[4];
        int sum;
        int r, g, b;
        Long probeSetId;
        Integer[] value;
        String curCytoband = "";
        String lastCytoband = "";
        int lastX = -100;
        int lastY = 0;

        for (Short index : ChrIdInterested) {
            x = 160;
            y = 5 * scaleY * index;
            step = 0;
            sum = 0;
            Arrays.fill(colorValue, 0);

            svg.setColor(Color.BLACK);
            svg.setFont(new Font(null, Font.BOLD, 24));
            svg.drawString(String.format("Chr_id = % 2d", index), 0, y);

            for (Map.Entry<Long, Integer[]> ps : results.probeSetGraph.get(index).entrySet()) {
                probeSetId = ps.getKey();
                value = ps.getValue();
                for (int j = 0; j < 4; j++) {
                    sum += value[j];
                    colorValue[j] += value[j];
                }
                step++;

                if (step > scaleX) {
                    r = 255 * colorValue[2] / sum;
                    g = 255 * colorValue[1] / sum;
                    b = 255 * colorValue[0] / sum;

                    try {
                        svg.setColor(new Color(r, g, b));
                    } catch (Exception e) {
                        System.err.println(e.getClass().getName() + ": " + e.getMessage());
                        System.exit(0);
                    }
                    x += sx;

                    svg.fillRect(x, y, sx, height);

                    sum = 0;
                    step = 0;
                    Arrays.fill(colorValue, 0);
                }

                curCytoband = CytobandCache.get(probeSetId);
                if (curCytoband.compareTo(lastCytoband) != 0) {
                    svg.setColor(Color.BLACK);
                    svg.setFont(new Font(null, Font.PLAIN, 8));
                    if (Math.abs(x - lastX) > 40) {
                        svg.drawString(String.format("[%s]", curCytoband), x, y - scaleY2);
                        lastX = x;
                        lastY = y - scaleY2;
                    } else { //上升过程
                        svg.drawString(String.format("[%s]", curCytoband), x, lastY - scaleY2);
                        lastX = x;
                        lastY = lastY - scaleY2;
                    }


                    lastCytoband = curCytoband;
                }
            }
            //还有最后不足scaleX的部分要处理
            if (step > 0) {
                r = 255 * colorValue[2] / sum;
                g = 255 * colorValue[1] / sum;
                b = 255 * colorValue[0] / sum;
                svg.setColor(new Color(r, g, b));
                x += sx;
                svg.fillRect(x, y, sx, height);
            }
        }

        svg.scale(0.2, 1.0);
        String s = svg.getSVGDocument();

        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String filename = String.format("..%1$sData%1$sResult_%2$s.svg",
                    File.separator, df.format(date));

            m_log.info("Writing " + filename);
            FileOutputStream fos = new FileOutputStream(filename);
            PrintStream ps = new PrintStream(fos);

            ps.print(s);

            ps.close();
            fos.close();
            m_log.info("completed!");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void drawSample(String sampleId) {
        BioSample sample = this.getSample(sampleId);

        int x, sx, step;
        step = 40;
        int scale = 15;

        int width = 200000 / scale;
        int height = 5 * scale * 26;
        SVGGraphics2D g = new SVGGraphics2D(width, height);

        for (Short index : ChrIdInterested) {

            Set<Segment> mergedSegs = new TreeSet<Segment>();
            Segment curSeg = null;
            int lastSegMean = 0;
            int currentSegMean = 0;
            for (Segment s : sample.getAllSegments(index)) {
                currentSegMean = (int) (s.purityCorrCopyNumber + 0.5);
                if (curSeg == null) {
                    curSeg = s;
                } else {
                    if (currentSegMean == lastSegMean) {
                        curSeg.Loci.putAll(s.Loci);
                    } else {
                        mergedSegs.add(curSeg);
                        curSeg = s;
                    }
                }
                lastSegMean = currentSegMean;
            }
            if (curSeg != null) {
                mergedSegs.add(curSeg);
            }
            x = 0;
            sx = 0;
            int currentSegValue = 0;
            int w;
            for (Segment s : mergedSegs) {
                currentSegValue = (int) (s.purityCorrCopyNumber + 0.5);

                double yvalue = currentSegValue / 4.0;
                //double ystd = 1 + s.robustStdHalfCopyNumber;
                double ystd = 1;

                int y = (int) (5 * scale * index - yvalue * scale);
                int yh = (int) (5 * scale * index - (yvalue + ystd) * scale);
                int yl = (int) (5 * scale * index - (yvalue - ystd) * scale);

                w = (int) (s.Loci.size() / step + 0.5);

                if (s.fVector.isNeutral) {
                    g.setColor(Color.GREEN);
                } else if (s.fVector.isDeletion) {
                    g.setColor(Color.CYAN);
                } else {
                    g.setColor(Color.PINK);
                }


                g.fillRoundRect(x, yh, w, yl - yh, 5, 5);

                g.setColor(Color.RED);
                g.drawLine(x, y, x + w, y);


                g.setColor(Color.BLACK);
                g.setFont(new Font(null, Font.PLAIN, 8));
                int textPos = (w > 30) ? x + w / 2 : x;
                g.drawString(String.format("[%d]", currentSegValue), textPos, yl - scale);

                sx = sx + s.Loci.size();
                x = sx / step;
            }
        }

        g.scale(0.2, 1.0);
        String s = g.getSVGDocument();

        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String filename = String.format("..%1$sData%1$sResult_%2$s_%3$s.svg",
                    File.separator, sampleId, df.format(date));
            FileOutputStream fos = new FileOutputStream(filename);
            PrintStream ps = new PrintStream(fos);

            m_log.info("\nWriting " + filename);
            ps.print(s);

            ps.close();
            fos.close();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void drawSampleToPic(String sampleId) {
        BioSample sample = this.getSample(sampleId);

        int x, sx, step;
        step = 40;
        int scale = 15;

        int width = 60000 / scale;
        int height = 5 * scale * 26;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();


        for (Short index : ChrIdInterested) {

            Set<Segment> mergedSegs = new TreeSet<Segment>();
            Segment curSeg = null;
            int lastSegMean = 0;
            int currentSegMean = 0;
            for (Segment s : sample.getAllSegments(index)) {
                currentSegMean = (int) (s.purityCorrCopyNumber + 0.5);
                if (curSeg == null) {
                    curSeg = s;
                } else {
                    if (currentSegMean == lastSegMean) {
                        curSeg.Loci.putAll(s.Loci);
                    } else {
                        mergedSegs.add(curSeg);
                        curSeg = s;
                    }
                }
                lastSegMean = currentSegMean;
            }
            if (curSeg != null) {
                mergedSegs.add(curSeg);
            }
            x = 0;
            sx = 0;
            int currentSegValue = 0;
            int w;
            for (Segment s : mergedSegs) {
                currentSegValue = (int) (s.purityCorrCopyNumber + 0.5);

                double yvalue = currentSegValue / 4.0;
                //double ystd = 1 + s.robustStdHalfCopyNumber;
                double ystd = 1;

                int y = (int) (5 * scale * index - yvalue * scale);
                int yh = (int) (5 * scale * index - (yvalue + ystd) * scale);
                int yl = (int) (5 * scale * index - (yvalue - ystd) * scale);

                w = (int) (s.Loci.size() / step + 0.5);

                if (s.fVector.isNeutral) {
                    g.setColor(Color.GREEN);
                } else if (s.fVector.isDeletion) {
                    g.setColor(Color.CYAN);
                } else {
                    g.setColor(Color.PINK);
                }


                g.fillRoundRect(x, yh, w, yl - yh, 5, 5);

                g.setColor(Color.RED);
                g.drawLine(x, y, x + w, y);


                g.setColor(Color.BLACK);
                g.setFont(new Font(null, Font.PLAIN, 10));
                int textPos = (w > 30) ? x + w / 2 : x;
                g.drawString(String.format("[%d]", currentSegValue), textPos, yl - scale);

                sx = sx + s.Loci.size();
                x = sx / step;
            }
        }

        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String filename = String.format("..%1$sData%1$sResult_%2$s_%3$s.png",
                    File.separator, sampleId, df.format(date));

            ImageIO.write(image, "PNG", new File(filename));
        } catch (Exception ex) {
            ex.printStackTrace();
        }


    }


    public void drawProbeSets(String sampleId) {
        BioSample sample = this.getSample(sampleId);

        int step = 20;
        int maxLength = 0;
        for (Short index : ChrIdInterested) {
            maxLength = Math.max(maxLength, sample.getAllProbeSets(index).size());
        }
        int estimatedLength = maxLength;
        int width = (int) (1.15 * estimatedLength / step);
        int height = 400 * 23;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        Stroke bs;
//        Stroke bs2;
        bs = new BasicStroke(2.0f);
//        bs2 = new BasicStroke(1, BasicStroke.CAP_BUTT,
//                BasicStroke.JOIN_BEVEL, 0,
//                new float[]{16, 4}, 0);
        g.setStroke(bs);

        int x, sx;

        Font f1 = new Font(null, Font.BOLD, 24);
        Font f2 = new Font(null, Font.BOLD, 12);

        for (Short index : ChrIdInterested) {
            x = 100;
            sx = 100 * step;

            g.setColor(Color.BLACK);
            g.setFont(f1);
            g.drawString(String.format("Chr_id = % 2d", index), 10, 400 * index - 200);
            g.drawString("LRR", 20, 400 * index - 100);
            g.drawString("BAF", 20, 400 * index + 40);

            for (ProbeSet p : sample.getAllProbeSets(index).values()) {

                if (p.data.Is_Valid) {
                    int y = calculateYPosition(index, p.data.LRR);

                    if (p.Is_CNProbe) {
                        g.setColor(Color.BLACK);
                    } else {
                        if (p.data.parent_segment.fVector.isNeutral) {
                            g.setColor(Color.GRAY);
                        } else if (p.data.parent_segment.fVector.isDeletion) {
                            g.setColor(Color.CYAN);
                        } else {
                            g.setColor(Color.MAGENTA);
                        }
                    }
                    g.fillRect(x, y, 1, 1);

                    if (p.Is_SNPProbe) {
                        int y2 = (int) (400 * index + 80 - p.data.BAF * 100);
                        if (p.data.isNotLOH) {
                            g.setColor(Color.ORANGE);
                        } else {
                            g.setColor(Color.BLUE);
                        }

                        g.fillRect(x, y2, 1, 1);
                    }
                    sx++;
                    x = sx / step;
                }
            }

            x = 100;
            sx = 100 * step;
            for (Segment s : sample.getAllSegments(index)) {
                //int y = calculateYPosition(index,s.robustMeanHalfCopyNumber);

                int y2 = calculateYPosition(index, BioToolbox.log2(Math.max(0.1, s.purityCorrCopyNumber)));

                if (s.fVector.isNeutral) {
                    g.setColor(Color.GREEN);
                } else if (s.fVector.isDeletion) {
                    g.setColor(Color.BLUE);
                } else {
                    g.setColor(Color.RED);
                }

                int w = (int) (s.Loci.size() / step + 0.5);
//                g.setStroke(bs);
////                g.drawLine(x, y, x + w, y);
//                g.setStroke(bs2);
                g.drawLine(x, y2, x + w, y2);

                g.setFont(f2);
                int textPos = (w > 30) ? x + w / 2 : x;
                g.drawString(String.format("[%.1f]", s.purityCorrCopyNumber), textPos, y2 - 6);


                sx = sx + s.Loci.size();
                x = (int) ((sx / step) + 0.5);
            }


        }
        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String filename = String.format("..%1$sData%1$sTestChrProbeSet_%2$s_%3$s.png",
                    File.separator, sampleId, df.format(date));

            ImageIO.write(image, "PNG", new File(filename));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public void drawProbeSets_forTest(String sampleId) {
        BioSample sample = this.getSample(sampleId);

        int step = 200;
        int estimatedLength = sample.getAllProbeSets(1).size();
        int width = (int) (1.15 * estimatedLength / step) + 100;
        int height = 400 * 23;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        Stroke bs;
//        Stroke bs2;
        bs = new BasicStroke(2.0f);
//        bs2 = new BasicStroke(1, BasicStroke.CAP_BUTT,
//                BasicStroke.JOIN_BEVEL, 0,
//                new float[]{16, 4}, 0);
        g.setStroke(bs);

        int x, sx;

        Font f1 = new Font(null, Font.BOLD, 24);
        Font f2 = new Font(null, Font.BOLD, 12);

        for (Short index : ChrIdInterested) {
            x = 100;
            sx = 100 * step;

            g.setColor(Color.BLACK);
            g.setFont(f1);
            g.drawString(String.format("Chr_id = % 2d", index), 10, 400 * index - 200);
            g.drawString("LRR", 20, 400 * index - 100);
            g.drawString("BAF", 20, 400 * index + 40);

            for (ProbeSet p : sample.getAllProbeSets(index).values()) {

                if (p.data.Is_Valid) {
                    int y = calculateYPosition(index, p.data.LRR);

                    g.setColor(Color.DARK_GRAY);
                    g.fillRect(x, y, 1, 1);

                    sx++;
                    x = sx / step;
                }
            }

            x = 100;
            sx = 100 * step;
            for (Segment s : sample.getAllSegments(index)) {
                int y = calculateYPosition(index, BioToolbox.log2(2 * s.robustMeanHalfCopyNumber));
                g.setColor(Color.RED);

                int w = (int) (s.Loci.size() / step + 0.5);
                g.drawLine(x, y, x + w, y);
                sx = sx + s.Loci.size();
                x = (int) ((sx / step) + 0.5);
            }


        }
        try {
            Date date = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String filename = String.format("..%1$sData%1$sTestChrProbeSet_Test_%2$s_%3$s.png",
                    File.separator, sampleId, df.format(date));

            ImageIO.write(image, "PNG", new File(filename));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    private final int calculateYPosition(int row, double value) {
        //return (int) (300 - value * 50) + 400*(row - 1);
        return (int) (340 - value * 50) + 400 * (row - 1);
    }

    public void printResultSummary() {
        StringBuilder temp = new StringBuilder();
        temp.append(String.format("\nSampleId\tPurity\tPloidy \n"));
        Set<String> sampleIdSet = new TreeSet<String>(samples.keySet());
        for (String sampldId : sampleIdSet) {
            if (results.containsSampleId(sampldId)) {
                temp.append(String.format("%s\t%.4f\t%.4f \n",
                        sampldId, results.getPurity(sampldId), results.getPloidy(sampldId)));
            } else {
                temp.append(String.format("%s\t NULL \t NULL \n",
                        sampldId));
            }

        }
        m_log.info(temp.toString());

    }

    public void saveToFile(String sampleId, String filename) {
        BioSample sample = this.getSample(sampleId);
        int sampleCount = 1;
        int probeCount = sample.getProbeSetCount(ChrIdInterested);
        double[] nA_array = new double[probeCount];
        double[] nB_array = new double[probeCount];
        double[] tA_array = new double[probeCount];
        double[] tB_array = new double[probeCount];
        Long[] id_array = new Long[probeCount];

        int n = 0;
        for (Short index : ChrIdInterested) {
            for (ProbeSet p : sample.getAllProbeSets(index).values()) {
                id_array[n] = p.Loci;
                nA_array[n] = p.data.Normal.mean_A;
                nB_array[n] = p.data.Normal.mean_B;
                tA_array[n] = p.data.Tumor.mean_A;
                tB_array[n] = p.data.Tumor.mean_B;

                n++;
            }
        }

        Map<String, double[]> nA_dataset = new TreeMap<String, double[]>();
        Map<String, double[]> nB_dataset = new TreeMap<String, double[]>();
        Map<String, double[]> tA_dataset = new TreeMap<String, double[]>();
        Map<String, double[]> tB_dataset = new TreeMap<String, double[]>();
        double[] maxMinArray = new double[4];
        maxMinArray[0] = 100;
        maxMinArray[1] = 0;
        maxMinArray[2] = 100;
        maxMinArray[3] = 0;

        double[] n_LogR = new double[probeCount];
        double[] n_BAF = new double[probeCount];
        double[] t_LogR = new double[probeCount];
        double[] t_BAF = new double[probeCount];
        for (int i = 0; i < probeCount; i++) {
            double nLogR = BioToolbox.log2(nA_array[i] + nB_array[i]);
            double nBAF = nB_array[i] / (nA_array[i] + nB_array[i]);
            double tLogR = BioToolbox.log2(tA_array[i] + tB_array[i]);
            double tBAF = tB_array[i] / (tA_array[i] + tB_array[i]);

            maxMinArray[0] = Math.min(nLogR, maxMinArray[0]);
            maxMinArray[1] = Math.max(nLogR, maxMinArray[1]);
            maxMinArray[2] = Math.min(tLogR, maxMinArray[2]);
            maxMinArray[3] = Math.max(tLogR, maxMinArray[3]);

            n_LogR[i] = nLogR;
            n_BAF[i] = nBAF;
            t_LogR[i] = tLogR;
            t_BAF[i] = tBAF;
        }
        n_LogR = BioToolbox.blur(n_LogR, 3);
        t_LogR = BioToolbox.blur(t_LogR, 3);
//        n_BAF = BioToolbox.blur(n_BAF,8);
//        t_BAF = BioToolbox.blur(t_BAF,8);

        double _min = Math.min(maxMinArray[0], maxMinArray[2]);
        double _max = Math.max(maxMinArray[1], maxMinArray[3]);

        for (int i = 0; i < probeCount; i++) {
            n_LogR[i] = 2 * (n_LogR[i] - _min) / (_max - _min) - 1;
            t_LogR[i] = 2 * (t_LogR[i] - _min) / (_max - _min) - 1;
        }

        BufferedWriter fw1 = null;
        BufferedWriter fw2 = null;
        BufferedWriter fw3 = null;
        BufferedWriter fw4 = null;

        try {
            File file1 = new File("..\\Data\\Germline_LogR.txt");
            File file2 = new File("..\\Data\\Germline_BAF.txt");
            File file3 = new File("..\\Data\\Tumor_LogR.txt");
            File file4 = new File("..\\Data\\Tumor_BAF.txt");
            fw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file1, true), "UTF-8"));
            fw2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file2, true), "UTF-8"));
            fw3 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file3, true), "UTF-8"));
            fw4 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file4, true), "UTF-8"));
            fw1.append(String.format("\tchrs\tpos\t%s", sampleId));
            fw2.append(String.format("\tchrs\tpos\t%s", sampleId));
            fw3.append(String.format("\tchrs\tpos\t%s", sampleId));
            fw4.append(String.format("\tchrs\tpos\t%s", sampleId));
            fw1.newLine();
            fw2.newLine();
            fw3.newLine();
            fw4.newLine();
            int count = 0;
            n = 0;

            for (int i = 0; i < probeCount; i++) {
                long loci = id_array[i];
                int[] pos = BioToolbox.getChrIdAndStartPosition(loci);
                n++;
                fw1.append(String.format("SNP%d\t%d\t%d\t%.4f", n, pos[0], pos[1], n_LogR[i]));
                fw1.newLine();
                fw2.append(String.format("SNP%d\t%d\t%d\t%.4f", n, pos[0], pos[1], n_BAF[i]));
                fw2.newLine();
                fw3.append(String.format("SNP%d\t%d\t%d\t%.4f", n, pos[0], pos[1], t_LogR[i]));
                fw3.newLine();
                fw4.append(String.format("SNP%d\t%d\t%d\t%.4f", n, pos[0], pos[1], t_BAF[i]));
                fw4.newLine();

                count++;
                if (count > 30000) {
                    count = 0;
                    System.out.println(pos[0] + ":" + pos[1]);
                }
            }

            fw1.flush(); // 全部写入缓存中的内容
            fw2.flush();
            fw3.flush();
            fw4.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fw1 != null) {
                try {
                    fw1.close();
                    fw2.close();
                    fw3.close();
                    fw4.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//    public void saveToFile( String sampleId, String filename){
//        BioSample sample = this.getSample(sampleId);
//        int sampleCount = 1;
//
//
//
//        Map<Long,double[][]> dataset = new TreeMap<Long, double[][]>();
//        double[] maxMinArray = new double[4];
//        maxMinArray[0] =  100;
//        maxMinArray[1] = 0;
//        maxMinArray[2] = 100;
//        maxMinArray[3] = 0;
//
//
//        for (Short index : ChrIdInterested) {
//            for (ProbeSet p : sample.getAllProbeSets(index).values()) {
//                double[][] values =  new double[sampleCount][4];
//                double nLogR = BioToolbox.log2(p.data.Normal.mean_A + p.data.Normal.mean_B);
//                double nBAF =  p.data.Normal.mean_B/(p.data.Normal.mean_A + p.data.Normal.mean_B);
//                double tLogR = BioToolbox.log2(p.data.Tumor.mean_A + p.data.Tumor.mean_B);
//                double tBAF =  p.data.Tumor.mean_B/(p.data.Tumor.mean_A + p.data.Tumor.mean_B);
//                values[0][0] = nLogR;
//                values[0][1] = nBAF;
//                values[0][2] = tLogR;
//                values[0][3] = tBAF;
//                dataset.put(p.Loci,values);
//
//                maxMinArray[0] = Math.min(nLogR, maxMinArray[0]);
//                maxMinArray[1] = Math.max(nLogR, maxMinArray[1]);
//                maxMinArray[2] = Math.min(tLogR, maxMinArray[2]);
//                maxMinArray[3] = Math.max(tLogR, maxMinArray[3]);
//            }
//        }
//        double _min = Math.min(maxMinArray[0],maxMinArray[2]);
//        double _max = Math.max(maxMinArray[1], maxMinArray[3]);
//
//        for(Map.Entry<Long,double[][]> data : dataset.entrySet()){
//            double[][] values = data.getValue();
//
//            values[0][0] = 2*(values[0][0] - _min)/(_max - _min) - 1;
//            values[0][2] = 2*(values[0][2] - _min)/(_max - _min) - 1;
//
//            dataset.put(data.getKey(),values);
//        }
//
//        BufferedWriter fw1 = null;
//        BufferedWriter fw2 = null;
//        BufferedWriter fw3 = null;
//        BufferedWriter fw4 = null;
//
//        try {
//            File file1 = new File("..\\Data\\Germline_LogR.txt");
//            File file2 = new File("..\\Data\\Germline_BAF.txt");
//            File file3 = new File("..\\Data\\Tumor_LogR.txt");
//            File file4 = new File("..\\Data\\Tumor_BAF.txt");
//            fw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file1, true), "UTF-8"));
//            fw2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file2, true), "UTF-8"));
//            fw3 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file3, true), "UTF-8"));
//            fw4 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file4, true), "UTF-8"));
//            fw1.append(String.format("\tchrs\tpos\t%s",sampleId));
//            fw2.append(String.format("\tchrs\tpos\t%s",sampleId));
//            fw3.append(String.format("\tchrs\tpos\t%s",sampleId));
//            fw4.append(String.format("\tchrs\tpos\t%s", sampleId));
//            fw1.newLine();
//            fw2.newLine();
//            fw3.newLine();
//            fw4.newLine();
//            int count = 0;
//            int n = 0;
//
//            for(Map.Entry<Long,double[][]> data : dataset.entrySet()){
//                long loci = data.getKey();
//                int[] pos = BioToolbox.getChrIdAndStartPosition(loci);
//                double[][] values = data.getValue();
//                n++;
//                fw1.append(String.format("SNP%d\t%d\t%d\t%.4f",n,pos[0],pos[1],values[0][0]));
//                fw1.newLine();
//                fw2.append(String.format("SNP%d\t%d\t%d\t%.4f",n,pos[0],pos[1],values[0][1]));
//                fw2.newLine();
//                fw3.append(String.format("SNP%d\t%d\t%d\t%.4f",n,pos[0],pos[1],values[0][2]));
//                fw3.newLine();
//                fw4.append(String.format("SNP%d\t%d\t%d\t%.4f",n,pos[0],pos[1],values[0][3]));
//                fw4.newLine();
//
//                count++;
//                if (count > 3000) {
//                    count = 0;
//                    System.out.println(pos[0] + ":" + pos[1]);
//                }
//            }
//
//            fw1.flush(); // 全部写入缓存中的内容
//            fw2.flush();
//            fw3.flush();
//            fw4.flush();
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            if (fw1 != null) {
//                try {
//                    fw1.close();
//                    fw2.close();
//                    fw3.close();
//                    fw4.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }
}

